package com.cell.utils;

import com.cell.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 应包含密码的加密解密，以及注册时各字段的合法性校验
 *
 * @author cloudJiang
 * @date 2022/5/12 20:31
 */
@Component
public class UserUtil {
    @Autowired
    private JavaMailSenderImpl mailSender;

    /**
     * 验证邮箱格式以及not null字段是否为空
     *
     * @param user
     * @throws Exception 验证不通过的异常
     */
    public void validateUser(User user) throws Exception {
        //验证邮箱的正则表达式
        String pattern = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";

        //空子段验证
        if (!(user.getNickname() == null || user.getPassword() == null || user.getLoginKey() == null || user.getCountry() == null
                || user.getProvince() == null || user.getCity() == null || user.getPhone() == null)) {

            //检验邮箱格式是否正确
            if (!Pattern.matches(pattern, user.getLoginKey())) {
                throw new Exception();
            }
        } else {
            throw new Exception();
        }
    }

    /**
     * 生成验证码
     *
     * @return
     */
    private String generateValidCode() {
        Random random = new Random();
        int i = random.nextInt() * 10000;
        return String.valueOf(i).substring(1, 5);
    }

    /**
     * 发送验证码到用户邮箱，并返回生成的验证码
     *
     * @param sendTo 用户邮箱
     * @return 生成的验证码
     */
    public String sendValidEMail(String sendTo) {
        SimpleMailMessage message = new SimpleMailMessage();
        String code = generateValidCode();
        message.setSubject("环绿回收验证码");
        message.setText("您正在重置您的密码，若非本人操作请无视。\n 验证码：" + code +
                "\n 验证码请勿告知他人，该验证码将在三十分钟后失效。");
        message.setTo(sendTo);
        message.setFrom("1215683942@qq.com");
        mailSender.send(message);
        return code;
    }

    /**
     * 使用MD5来实现对密码的单向加密，之后再截取一半加密后的密码进行md5加密，最终生成48位密文，
     * 且加密算法为单向，且无法使用通用的彩虹表反推密码，提高安全性
     *
     * @param password
     * @return 加密后的密文
     * @throws NoSuchAlgorithmException
     */
    public String encryptByMD5(byte[] password) throws NoSuchAlgorithmException {
        StringBuilder stringBuilder = new StringBuilder();

        MessageDigest md5 = MessageDigest.getInstance("MD5");
        md5.update(password);
        byte[] temp1 = md5.digest();
        //将密文转为十六进制后存储入string
        for (byte b : temp1) {
            stringBuilder.append(String.format("%02x", new Integer(b & 0xff)));
        }
        String temp1_s = stringBuilder.toString();
        //清空该builder以及MessageDigest等待下次使用
        stringBuilder.delete(0, stringBuilder.length());
        md5.reset();

        //再次加密
        md5.update(temp1_s.substring(16).getBytes(StandardCharsets.UTF_8));
        byte[] temp2 = md5.digest();
        //将密文转为string
        for (byte b : temp2) {
            stringBuilder.append(String.format("%02x", new Integer(b & 0xff)));
        }
        String temp2_s = stringBuilder.toString();

        return temp1_s.substring(0, 16) + temp2_s;
    }
}
